package water.com.RequestParse;

import water.com.Aop.WaterOutHandler;
import water.com.Ioc.WaterSmartBeanFactory;
import water.com.Service.base.BaseCore;
import water.com.Service.entity.In.BaseIn;
import water.com.Service.entity.Out.BaseOut;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import lombok.SneakyThrows;
import water.com.util.ConfigurationReader;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.nio.charset.StandardCharsets;
import java.util.Map;


public class WaterHttpHandler implements HttpHandler {

    private final Map<String,Class<?>> serviceMap;
    private static BaseOut Out = null;
    private static String  coreIn = null;

    public WaterHttpHandler(Map<String,Class<?>> serviceMap){
        this.serviceMap=serviceMap;
        coreIn =(String) ConfigurationReader.getInstance().getValueByKey("server","coreIn");
        if(Out==null){
            Out = new BaseOut();
            Out.setBaseBody(new BaseOut.BaseBody());
        }
    }
    /**
     *请求处理器: 它的作用是拦截无效请求，并根据请求报文调用对应的接口
     * @param httpExchange 交互模型
     */
    @SneakyThrows
    @SuppressWarnings({"unchecked"})
    @Override
    public void handle(HttpExchange httpExchange){
        String responseJson;
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            //获取Json格式的请求报文字符串
            String requestJson = getRequestParam(httpExchange);
            String serviceId = getServiceId(requestJson);
            if(serviceId!=null){
                if(serviceMap.containsKey(serviceId)){
                    Class<?> inType = Class.forName(coreIn+"."+serviceId+"In");
                    BaseIn coreIn = (BaseIn) objectMapper.readValue(requestJson, inType);
                    Class<?> serviceCl = serviceMap.get(serviceId);
                    BaseCore<BaseIn,BaseOut> serviceCore = (BaseCore<BaseIn, BaseOut>) WaterSmartBeanFactory.pollBean(serviceCl.getSimpleName());
                    try{
                        //代理实现接口动态调用
                        InvocationHandler handler = new WaterOutHandler(serviceCore);
                        BaseCore<BaseIn,BaseOut> proxy =(BaseCore<BaseIn, BaseOut>) Proxy.newProxyInstance(serviceCore.getClass().getClassLoader(),
                                serviceCore.getClass().getInterfaces(),handler);
                        proxy.check(coreIn);
                        Object responseObj = proxy.execute(coreIn);
                        responseJson = objectMapper.writeValueAsString(responseObj);
                        //返回响应报文信息
                        handleResponse(httpExchange,responseJson);
                    }catch (Exception e){
                        e.printStackTrace();
                        if(e.getMessage().contains("check")){
                            Out.getBaseBody().setErrInfo(e.getMessage().replace("check:",""));
                        }else {
                            Out.getBaseBody().setErrInfo("999999异常");
                        }
                        responseJson = objectMapper.writeValueAsString(Out);
                        handleResponse(httpExchange,responseJson);
                    }finally {
                        WaterSmartBeanFactory.addBean(serviceCore);
                    }
                }else {
                    //提示报文中的serviceId输入有误
                    Out.getBaseBody().setErrInfo("请检查报文中serviceId的值上是否正确！！");
                    responseJson = objectMapper.writeValueAsString(Out);
                    handleResponse(httpExchange,responseJson);
                }
            }else{
                //提示报文中的serviceId必输
                Out.getBaseBody().setErrInfo("serviceId必输！！");
                responseJson = objectMapper.writeValueAsString(Out);
                handleResponse(httpExchange,responseJson);
            }

        } catch (Exception ex) {
            ex.printStackTrace();
            //提示报文字段有误
            Out.getBaseBody().setErrInfo("请检查报文中的字段上是否正确！！");
            responseJson = objectMapper.writeValueAsString(Out);
            handleResponse(httpExchange,responseJson);
        }
    }

    /**
     * 获取请求参数
     * @param httpExchange 交互模型
     * @return 返回请求报文字符串
     * @throws Exception
     */
    private String getRequestParam(HttpExchange httpExchange) throws IOException {
        String paramStr = "";

        if (httpExchange.getRequestMethod().equals("GET")) {
            //GET请求读queryString
            paramStr = httpExchange.getRequestURI().getQuery();
        } else {
            //非GET请求读请求体
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpExchange.getRequestBody(),StandardCharsets.UTF_8));
            StringBuilder requestBodyContent = new StringBuilder();
            String line = null;
            while ((line = bufferedReader.readLine()) != null) {
                requestBodyContent.append(line);
            }
            paramStr = requestBodyContent.toString();
        }

        return paramStr;
    }

    /**
     * 处理响应给前端
     * @param httpExchange 交互模型
     * @param responseText 返回报文
     * @throws Exception
     */
    private void handleResponse(HttpExchange httpExchange, String responseText) throws IOException {
        //生成响应报文
        byte[] responseContentByte = responseText.getBytes(StandardCharsets.UTF_8);

        //设置响应头，必须在sendResponseHeaders方法之前设置！
        httpExchange.getResponseHeaders().add("Content-Type:", "text/json;charset=utf-8");

        //设置响应码和响应体长度，必须在getResponseBody方法之前调用！
        httpExchange.sendResponseHeaders(200, responseContentByte.length);

        OutputStream out = httpExchange.getResponseBody();
        out.write(responseContentByte);
        out.flush();
        out.close();
    }

    /**
     * 获取到服务码
     * @param requestJson 请求报文
     * @return 服务码
     */
    private String getServiceId(String requestJson){
        String serviceId=null;
        if(requestJson.equals("")){
            return null;
        }
        int index= requestJson.indexOf("serviceId");
        if(index==-1){
            return null;
        }
        String temp=requestJson.substring(index);
        int index1 = temp.indexOf(":");
        int index2 = temp.indexOf(",");
        String target=temp.substring(index1+1,index2);
        target = target.trim();
        serviceId=target.substring(1,target.length()-1);

        return serviceId;
    }
}
